package ija.model;

import ija.model.basis.Desk;
import ija.model.history.History;
import ija.model.players.Player;
import ija.model.types.FigureColor;
import ija.xls.notation.GameMove;
import ija.xls.notation.NotationReaderFactory;

import java.io.IOException;
import java.io.PrintStream;

/**
 * Rozhraní modelu hry. Datová část MVC architektury, využívané pro věh hry.
 * 
 * @author Radek Nečas, xnecas18
 */
public interface GameModel {

    /**
     * Inicializování hrací desky. Metoda naplní šachovnici figurkami do
     * základního postavení.
     * 
     * @param topPlayerColor
     *            udává jakou barvu budou mít figurky v horní části šachovnice
     *            (od řádku: 8).
     */
    public void initGame(FigureColor topPlayerColor);

    /**
     * Inicializuje xml vstup.
     * 
     * @param filename
     *            nazev xml souboru
     * @return true ok, false chyba
     */
    public boolean initInputXml(String filename);

    /**
     * Naplni sachovnici figurkami dane barvy z xml.
     * 
     * @param color
     *            barva figurky
     * @return true ok, false chyba
     */
    public boolean initFigureXml(FigureColor color);

    /**
     * Inicializuje hru z xml. Naplni sachovnici figurkami vsech barev.
     * 
     * @return true OK, false chyba
     */
    public boolean initGameXml();

    /**
     * Inicializuje hrace z xml
     * 
     * @return true OK, false chyba
     */
    public boolean initPlayersXml();

    /**
     * Inicializuje stav historie z xml.
     * 
     * @return true OK, false chyba.
     */
    public boolean initHistoryXml();

    /**
     * Inicializuje stav modelu z xml objektu. Predpoklada, ze objekt jiz bude
     * vytvoren a naplnen.
     * 
     * @return true OK, false chyba
     */
    public boolean initFromXml();

    /**
     * Inicializuje stav modelu z xml souboru.
     * 
     * @param filename
     *            cesta k xml souboru
     * @return indikator uspechu operace. True OK, false chyba
     */
    public boolean initFromXml(String filename);

    /**
     * Provádí pohyb figurky. Aktualizuje všechny související objekty (figurky,
     * pozice v dané šachovnici). Pozice musí být na téže šachovnici (ale není
     * testováno).
     * 
     * @param moveDescription
     *            popisuje pohyb (počáteční, koncová pozice, operace)
     * @return true pokud dojde ke změně modelu, jinak false
     */
    public boolean move(GameMove moveDescription);

    /**
     * Metoda pro nastavení hráče
     * 
     * @param id
     *            identifikator hráče, jenž se bude nastavovat (povolené 0 a 1).
     * @param p
     *            hráč který se nastaví (zkopíruje se odkaz)
     * @return true pokud je hráč nastaven, false při chybě (špatné id)
     */
    public boolean setPlayer(int id, Player p);

    /**
     * Metoda nastavi desku dle jine desky. Vsechny aktualni figurky budou
     * straceny a budou nastaveny figurky nove. Rozmery desky se take nastavuji
     * dle nove desky. Metoda informuje observery.
     * 
     * @param otherDesk
     *            deska, podle ktere bude deska modelu nastavena.
     */
    public void setDesk(Desk otherDesk);

    /**
     * Metoda pro získání hráče.
     * 
     * @param id
     *            identifikátor hráče (povolené hodnoty 0 a 1).
     * @return hráč nebo null při chybě (špatné id)
     */
    public Player getPlayer(int id);

    /**
     * Vrátí aktivního hráče
     * 
     * @return aktivní hráč
     */
    public Player getActivePlayer();

    /**
     * Aktivuje určeného hráče. Pokud není metoda volána, je automaticky aktivní
     * hráč 0. Informuje observer.
     * 
     * @param id
     *            identifikátor hráče, jenž má být aktivován
     * @return true ok, jinak false (špatné id)
     */
    public boolean activatePlayer(int id);

    /**
     * Aktivuje určeného hráče. Pokud není metoda volána, je automaticky aktivní
     * hráč 0. Informuje observer.
     * 
     * @param c
     *            barva hráče, jenž má být aktivován
     * @return true ok, jinak false (špatné id)
     */
    public boolean activatePlayer(FigureColor c);

    /**
     * Aktivuje dalšího hráče (toho, který je na řadě).
     */
    public Player nextPlayer();

    /**
     * Zrusi vsechny hrace a nastavi aktivniho hrace na 0 (vychozi hodnota).
     */
    public void clearPlayers();

    /**
     * Metoda pro získání šachovnice. Skrze šachovnici se poté získávají další
     * informace (pozice, figurky). Získané objekty slouží jen pro čtení. Neměli
     * by se přímo měnit.
     * 
     * @return šachovnice, v níž jsou umístěny figurky
     */
    public Desk getDesk();

    public void clearDesk();

    /**
     * Vrati historii hry
     * 
     * @return historie hry
     */
    public History getHistory();

    /**
     * Inicializuje xml vystup
     * 
     * @param notType
     *            typ notace, ktera se pouziva ve hre a ve ktere bude ulozena
     *            historie v xml
     */
    public void initOutputXml(NotationReaderFactory.NotationType notType);

    /**
     * Ulozi vsechny hrace do xml.
     */
    public void savePlayersXml();

    /**
     * Ulozi do xml celou historii.
     */
    public void saveHistoryXml();

    /**
     * Ulozi do xml aktualni stav desky - vsechny figurky na desce. Slouzi pri
     * ulozeni rozehrane hry. Tento stav se pote muze obnovit.
     */
    public void saveDeskStateXml();

    /**
     * Ulozi do xml cely model. Uklada hrace, historii a stav desky
     */
    public void saveAllXml();

    /**
     * Zapise xml do souboru. Predpoklada, ze xml objekty budou naplneny daty,
     * jinak vytvori jen dokument s korenovym elementem.
     * 
     * @param filename
     *            nazev souboru kam se bude xml zapisovat
     * @throws IOException
     *             chyba pri praci se soubory
     */
    public void writeXml(String filename) throws IOException;

    /**
     * Zapise xml do PrintStreamu. Predpoklada, ze xml objekty budou naplneny
     * daty, jinak vytvori jen dokument s korenovym elementem.
     * 
     * @param output
     *            PrintStream do ktereho se bude zapisovat.
     * @throws IOException
     *             chyba pri praci se soubory
     */
    public void writeXml(PrintStream output) throws IOException;

    /**
     * Ulozi cely stav modelu do xml a to pote zapise do souboru. Uklada hrace,
     * historii a stav desky.
     * 
     * @param filename
     *            nazev souboru, kam bude xml ulozeno.
     * @throws IOException
     *             chyba pri praci se soubory
     */
    public void saveAllXmlAndWrite(String filename) throws IOException;

    /**
     * Ulozi cely stav modelu do xml a to pote zapise do PrintStreamu. Uklada
     * hrace, historii a stav desky.
     * 
     * @param output
     *            PrintStream do ktereho se bude zapisovat.
     * @throws IOException
     *             chyba pri praci se streamy.
     */
    public void saveAllXmlAndWrite(PrintStream output) throws IOException;

}
